package com.thirdGd;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONObject;
import com.thirdGd.annotation.*;
import com.thirdGd.builder.SFItemBuilder;
import com.thirdGd.po.SFObject;
import com.thirdGd.po.SFSchemaEnumObject;
import com.thirdGd.po.SFUIGridObject;
import com.thirdGd.po.SFUIObject;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;


public class ThirdGdCommUtils {
    /**
     * 把对象转为map
     *
     * @param obj Object
     * @return Map
     */
    public static Map<String, Object> convertToMap(Object obj) {
        return BeanUtil.beanToMap(obj);
    }

    /**
     * 把map转为json对象
     *
     * @param map Map
     * @return
     */
    public static JSONObject convertToJson(Map<String, Object> map) {
        // 对Property进行循环处理
        if (map.containsKey("properties") && map.get("properties") instanceof Map) {
            Map<String, Object> properties = (Map<String, Object>) map.get("properties");
            for (String key : properties.keySet()) {
                Map<String, Object> propertiesOfKye = reWritePropertyMap(BeanUtil.beanToMap(properties.get(key)));
                properties.put(key, propertiesOfKye);
            }
        }
        return new JSONObject(map, true);
    }

    /**
     * 重写某些map里的关键字段值
     *
     * @param map Map
     * @return
     */
    public static Map<String, Object> reWritePropertyMap(Map<String, Object> map) {
        if (map.containsKey("xDefault")) {
            Object objD = map.get("xDefault");
            map.remove("xDefault");
            map.put("default", objD);
        }
        if (map.containsKey("xEnum")) {
            Object objE = map.get("xEnum");
            map.remove("xEnum");
            map.put("enum", objE);
        }
        return map;
    }


    /**
     * 获取对象的所有数据字段
     *
     * @param clazz
     * @return
     */
    public static Field[] getField(Class<?> clazz) {
        Field[] fields = ReflectUtil.getFields(clazz);
        Stream<Field> fieldStream = CollUtil.toList(fields).stream()
                .filter(field -> ObjectUtil.isNotNull(field.getAnnotation(SFString.class))
                        || ObjectUtil.isNotNull(field.getAnnotation(SFEnum.class))
                        || ObjectUtil.isNotNull(field.getAnnotation(SFBoolean.class))
                        || ObjectUtil.isNotNull(field.getAnnotation(SFRadio.class))
                        || ObjectUtil.isNotNull(field.getAnnotation(SFSelect.class)));
        return fieldStream.toArray(Field[]::new);
    }

    /**
     * @param fieldName
     * @param o
     * @return
     * @desc 根据属性名获取属性值
     */
    public static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter);
            return method.invoke(o);
        } catch (Exception ignored) {

        }
        return null;
    }

    /**
     * 获取类成员方法的返回结果
     *
     * @param clazz
     * @param active
     * @return
     */
    public static Object getValuesFromClassAndAction(Class<?> clazz, String active) {
        try {
            Method m = clazz.getMethod(active);
            return m.invoke(clazz);

        } catch (Exception ignored) {

        }
        return null;
    }

    /**
     * 获取对应的enum值得标识
     *
     * @param o Object
     * @return Map<String, Object>
     */
    public static Map<String, Object> getSFItemsEnums(Object o) {
        Field[] fields = getField(o.getClass());
        Map<String, Object> enumsValues = new HashMap<>();
        Field[] SFEnumFields = CollUtil.toList(fields).stream()
                .filter(field -> ObjectUtil.isNotNull(field.getAnnotation(SFEnum.class))).toArray(Field[]::new);
        CollUtil.toList(SFEnumFields).forEach((Field filed) -> {
            enumsValues.put(filed.getAnnotation(SFEnum.class).name(), ThirdGdCommUtils.getFieldValueByName(filed.getName(), o));
        });
        return enumsValues;
    }

    public static List<SFSchemaEnumObject> getSFItemEnum(Object o, String itemName) {
        Field[] fields = getField(o.getClass());
        Field[] enumFields = CollUtil.toList(fields).stream()
                .filter(field ->
                        ObjectUtil.isNotNull(field.getAnnotation(SFEnum.class))
                                && field.getAnnotation(SFEnum.class).name().equals(itemName)
                ).toArray(Field[]::new);
        if (enumFields.length > 0) {
            Field field = CollUtil.toList(enumFields).get(0);
            return (List<SFSchemaEnumObject>) ThirdGdCommUtils.getFieldValueByName(field.getName(), o);
        }
        return null;
    }

    /**
     * 获取基础的SF表单数据结构
     *
     * @param o Object
     * @return
     */
    public static SFObject makeBaseSFObject(Object o) {
        SFObject sfObject = new SFObject();
        // 根据注解生成UI样式
        SFUI sfui = o.getClass().getAnnotation(SFUI.class);
        SFUIGrid sfuiGrid = o.getClass().getAnnotation(SFUIGrid.class);
        SFUIObject ui;
        if (ObjectUtil.isNotNull(sfui) && ObjectUtil.isNotNull(sfuiGrid)) {
             ui = new SFUIObject(sfui.spanLabel(), sfui.spanControl(), new SFUIGridObject(sfuiGrid.span()));
        } else {
             ui =new SFUIObject(8, 16, new SFUIGridObject(24));
        }
        SFOrder sfOrder = o.getClass().getAnnotation(SFOrder.class);
        if(ObjectUtil.isNotNull(sfOrder)){
            String[] strings = sfOrder.order().split(",");
            for (String str : strings) {
                if (str != null && str.length() != 0) {
                    ui.addOrderKey(str);
                }
            }
            ui.addOrderKey("*");
        }
        sfObject.setUi(ui);
        // 根据注解生成必填字段
        SFRequired sfRequired = o.getClass().getAnnotation(SFRequired.class);
        if (ObjectUtil.isNotNull(sfui)) {
            String[] strings = sfRequired.keys().split(",");
            for (String str : strings) {
                if (str != null && str.length() != 0) {
                    sfObject.addRequiredKey(str);
                }
            }
        }
        return sfObject;
    }

    /**
     * 生成表单的Input框
     *
     * @param sfObj SFObject
     * @param field Field
     * @param o     Object
     */
    public static void addStringItem(SFObject sfObj, Field field, Object o) {
        SFString sfString = field.getAnnotation(SFString.class);
        if (ObjectUtil.isNotNull(sfString)) {
            sfObj.addProperty(
                    field.getName(),
                    SFItemBuilder.buildInput(
                            sfString,
                            ThirdGdCommUtils.getFieldValueByName(field.getName(), o)));
        }
    }

    /**
     * 生成Radio选择框
     * @param sfObj SFObject
     * @param field Field
     * @param o Object
     */
    public static void addRadioItem(SFObject sfObj, Field field, Object o){
        SFRadio sfSelect = field.getAnnotation(SFRadio.class);
        if (ObjectUtil.isNotNull(sfSelect)) {
            sfObj.addProperty(
                    field.getName(),
                    SFItemBuilder.buildRadio(
                            sfSelect,
                            ThirdGdCommUtils.getSFItemEnum(o, field.getName()),
                            ThirdGdCommUtils.getFieldValueByName(field.getName(), o)
                    ));
        }
    }

    /**
     * 生成下拉选择框
     * @param sfObj SFObject
     * @param field Field
     * @param o Object
     */
    public static void addSelectItem(SFObject sfObj, Field field, Object o){
        SFSelect sfSelect = field.getAnnotation(SFSelect.class);
        if (ObjectUtil.isNotNull(sfSelect)) {
            sfObj.addProperty(
                    field.getName(),
                    SFItemBuilder.buildSelect(
                            sfSelect,
                            ThirdGdCommUtils.getSFItemEnum(o, field.getName()),
                            ThirdGdCommUtils.getFieldValueByName(field.getName(), o)
                    ));
        }
    }

    /**
     * 生成表单的开关切换框
     *
     * @param sfObj SFObject
     * @param field Field
     * @param o     Object
     */
    public static void addBooleanItem(SFObject sfObj, Field field, Object o) {
        SFBoolean sfBoolean = field.getAnnotation(SFBoolean.class);
        if (ObjectUtil.isNotNull(sfBoolean)) {
            sfObj.addProperty(
                    field.getName(),
                    SFItemBuilder.buildBoolean(
                            sfBoolean,
                            ThirdGdCommUtils.getFieldValueByName(field.getName(), o)));
        }
    }

}
